#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <cstdlib>
#include <ctime>
#include <algorithm>

using namespace std;

struct Student {
    string id;
    string name;
    int scores[6];
    double average;
};

void generateScores(Student& student) {
    for (int i = 0; i < 6; ++i) {
        student.scores[i] = rand() % 101;
    }
}

string generateName() {
    static const char alphanum[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    string name = "Stude";
    for (int i = 0; i < 3; ++i) {
        name += alphanum[rand() % (sizeof(alphanum) - 1)];
    }
    return name;
}

void writeBinary(ofstream& file, const Student& student) {
    int idSize = student.id.size();
    int nameSize = student.name.size();
    file.write(reinterpret_cast<const char*>(&idSize), sizeof(int));
    file.write(student.id.c_str(), idSize);
    file.write(reinterpret_cast<const char*>(&nameSize), sizeof(int));
    file.write(student.name.c_str(), nameSize);
    for (int i = 0; i < 6; ++i) {
        file.write(reinterpret_cast<const char*>(&student.scores[i]), sizeof(int));
    }
    file.write(reinterpret_cast<const char*>(&student.average), sizeof(double));
}

void writeText(ofstream& file, const Student& student) {
    file << student.id << " " << student.name << " ";
    for (int i = 0; i < 6; ++i) {
        file << student.scores[i] << " ";
    }
    file << student.average << endl;
}

void readBinary(ifstream& file, Student& student) {
    int idSize, nameSize;
    file.read(reinterpret_cast<char*>(&idSize), sizeof(int));
    student.id.resize(idSize);
    file.read(&student.id[0], idSize);
    file.read(reinterpret_cast<char*>(&nameSize), sizeof(int));
    student.name.resize(nameSize);
    file.read(&student.name[0], nameSize);
    for (int i = 0; i < 6; ++i) {
        file.read(reinterpret_cast<char*>(&student.scores[i]), sizeof(int));
    }
    file.read(reinterpret_cast<char*>(&student.average), sizeof(double));
}

void readText(ifstream& file, Student& student) {
    file >> student.id >> student.name;
    for (int i = 0; i < 6; ++i) {
        file >> student.scores[i];
    }
    file >> student.average;
}

void sortByAverage(Student students[], int size) {
    sort(students, students + size, [](const Student& a, const Student& b) {
        return a.average > b.average;
        });
}

void addRank(Student students[], int size) {
    for (int i = 0; i < size; ++i) {
        cout << i + 1 << " " << students[i].id << " " << students[i].name << " ";
        for (int j = 0; j < 6; ++j) {
            cout << students[i].scores[j] << " ";
        }
        cout << students[i].average << endl;
    }
}

void generateFiles() {
    srand(time(0));
    for (int classNum = 1; classNum <= 5; ++classNum) {
        ofstream binFile("in" + to_string(classNum) + ".bin", ios::binary);
        ofstream txtFile("in" + to_string(classNum) + ".txt");
        for (int i = 0; i < 50; ++i) {
            Student student;
            student.id = "00000000" + to_string(i + 1);
            student.name = generateName();
            generateScores(student);
            double sum = 0;
            for (int j = 0; j < 6; ++j) {
                sum += student.scores[j];
            }
            student.average = sum / 6;
            writeBinary(binFile, student);
            writeText(txtFile, student);
        }
        binFile.close();
        txtFile.close();
    }
}

void calculateAverages() {
    for (int classNum = 1; classNum <= 5; ++classNum) {
        ifstream binFile("in" + to_string(classNum) + ".bin", ios::binary);
        ofstream outBinFile("out" + to_string(classNum) + ".bin", ios::binary);
        ofstream outTxtFile("out" + to_string(classNum) + ".txt");
        Student students[50];
        for (int i = 0; i < 50; ++i) {
            readBinary(binFile, students[i]);
            double sum = 0;
            for (int j = 0; j < 6; ++j) {
                sum += students[i].scores[j];
            }
            students[i].average = sum / 6;
            writeBinary(outBinFile, students[i]);
            writeText(outTxtFile, students[i]);
        }
        binFile.close();
        outBinFile.close();
        outTxtFile.close();
    }
}

void sortAndAddRank() {
    for (int classNum = 1; classNum <= 5; ++classNum) {
        ifstream binFile("out" + to_string(classNum) + ".bin", ios::binary);
        ofstream sortedBinFile("sorted_out" + to_string(classNum) + ".bin", ios::binary);
        ofstream sortedTxtFile("sorted_out" + to_string(classNum) + ".txt");
        Student students[50];
        for (int i = 0; i < 50; ++i) {
            readBinary(binFile, students[i]);
        }
        binFile.close();
        sortByAverage(students, 50);
        for (int i = 0; i < 50; ++i) {
            writeBinary(sortedBinFile, students[i]);
            sortedTxtFile << i + 1 << " ";
            writeText(sortedTxtFile, students[i]);
        }
        sortedBinFile.close();
        sortedTxtFile.close();
    }
}

void mergeAndSortAll() {
    Student allStudents[250];
    int index = 0;
    for (int classNum = 1; classNum <= 5; ++classNum) {
        ifstream binFile("sorted_out" + to_string(classNum) + ".bin", ios::binary);
        for (int i = 0; i < 50; ++i) {
            readBinary(binFile, allStudents[index++]);
        }
        binFile.close();
    }
    sortByAverage(allStudents, 250);
    ofstream finalBinFile("out.bin", ios::binary);
    ofstream finalTxtFile("out.txt");
    for (int i = 0; i < 250; ++i) {
        writeBinary(finalBinFile, allStudents[i]);
        finalTxtFile << i + 1 << " ";
        writeText(finalTxtFile, allStudents[i]);
    }
    finalBinFile.close();
    finalTxtFile.close();
}

void searchStudent() {
    string id;
    cout << "Enter student ID: ";
    cin >> id;
    ifstream finalBinFile("out.bin", ios::binary);
    Student student;
    bool found = false;
    while (finalBinFile.peek() != EOF) {
        readBinary(finalBinFile, student);
        if (student.id == id) {
            found = true;
            cout << "Student found: " << student.id << " " << student.name << " ";
            for (int i = 0; i < 6; ++i) {
                cout << student.scores[i] << " ";
            }
            cout << student.average << endl;
            break;
        }
    }
    if (!found) {
        cout << "Student not found." << endl;
    }
    finalBinFile.close();
}

int main() {
    generateFiles();
    calculateAverages();
    sortAndAddRank();
    mergeAndSortAll();
    searchStudent();
    return 0;
}
